package com.wiscamp.ninechapters.common.encrypt;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;

/**
 * DES Helper
 */
public class DesHelper {

    private DesHelper() {
    }

    private static final Logger logger = LoggerFactory.getLogger(DesHelper.class);

    private static final String PASSWORD = "9588028820109132570743325311888426347857298778549468758875018579537758772163084478873699447306034466200616411960574122434059469100235892702736860872901247123456";

    /**
     * 加密文本
     *
     * @param text String
     * @return String
     */
    public static String encryptText(String text) {
        try {
            byte[] bytes = text.getBytes();
            var random = new SecureRandom();
            var desKey = new DESKeySpec(PASSWORD.getBytes());
            // 创建一个密匙工厂，然后用它把DESKeySpec转换成
            var keyFactory = SecretKeyFactory.getInstance("DES");
            var secureKey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成加密操作
            var cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, secureKey, random);
            // 现在，获取数据并加密, 正式执行加密操作
            return new String(cipher.doFinal(bytes));
        } catch (Exception e) {
            logger.error("Failed to encrypt the text.", e);
        }
        return null;
    }

    /**
     * 解密文本
     *
     * @param text String
     * @return String
     * @throws Exception
     */

    public static String decryptText(String text) {
        try {
            byte[] bytes = text.getBytes();
            // DES算法要求有一个可信任的随机数源
            var random = new SecureRandom();
            // 创建一个DESKeySpec对象
            var desKey = new DESKeySpec(PASSWORD.getBytes());
            // 创建一个密匙工厂
            var keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            var secureKey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成解密操作
            var cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, secureKey, random);
            // 真正开始解密操作
            return new String(cipher.doFinal(bytes));
        } catch (Exception ex) {
            logger.error("Failed to decrypt the text.", ex);
        }
        return "";
    }

    /**
     * DES加密算法
     *
     * @param mode 模式： 加密，解密
     * @param data 需要加密的内容
     * @param key  密钥 8个字节数组
     * @return 将内容加密后的结果也是byte[]格式的
     */
    private static byte[] des(int mode, byte[] data, byte[] key) {
        byte[] ret = null;
        // 加密的内容存在并且密钥存在且长度为8个字节
        if (data != null && data.length > 0 && key != null && key.length == 8) {
            try {
                var cipher = Cipher.getInstance("DES");
                var keySpec = new DESKeySpec(key);
                var keyFactory = SecretKeyFactory.getInstance("DES");
                var secretKey = keyFactory.generateSecret(keySpec);
                cipher.init(mode, secretKey);
                ret = cipher.doFinal(data);
            } catch (Exception e) {
                logger.error("Failed to encrypt the data by DES.", e);
            }
        }
        return ret;
    }

    /**
     * DES 加密
     *
     * @param data
     * @param key
     * @return
     */
    public static byte[] desEncrypt(byte[] data, byte[] key) {
        return des(Cipher.ENCRYPT_MODE, data, key);
    }

    /**
     * DES 解密
     *
     * @param data
     * @param key
     * @return
     */
    public static byte[] desDecrypt(byte[] data, byte[] key) {
        return des(Cipher.DECRYPT_MODE, data, key);
    }
}
